package com.viknix.threadpool.manager.common.util;

import com.viknix.threadpool.manager.common.model.PoolParameterInfo;
import org.apache.commons.lang3.StringUtils;

import java.util.UUID;

/**
 * @Author: Dongqi
 * @Date: 2021/11/01 10.06
 * @Version 1.0
 * @Description: groupKey 格式：threadPoolId + projectId + namespace
 */
public class GroupKeyUtil {

    public static String getKey(String dataId, String group, String datumStr) {
        return doGetKey(dataId, group, datumStr);
    }

    private static String doGetKey(String dataId, String group, String datumStr) {
        StringBuilder sb = new StringBuilder();
        urlEncode(dataId, sb);
        sb.append('+');
        urlEncode(group, sb);
        sb.append('+');
        urlEncode(datumStr, sb);
        return sb.toString();
    }

    public static String getGroupKey(PoolParameterInfo parameterInfo) {
        return doGetKey(parameterInfo.getThreadPoolId(), parameterInfo.getItem(), parameterInfo.getNamespace());

    }

    /**
     * 将 groupKey 切分为String数组返回
     *
     * @param groupKey threadPoolId + projectId + namespace
     * @return threadPoolId、projectId、namespace 构成的String数组
     */
    public static String[] parseKey(String groupKey) {
        StringBuilder sb = new StringBuilder();
        String threadPoolId = null;
        String projectId = null;
        String namespace = null;

        for (int i = 0; i < groupKey.length(); ++i) {
            // 指针只想当前需要处理的字符
            char c = groupKey.charAt(i);
            // 如果是 +
            if ('+' == c) {
                // 如果 threadPoolId 还没被赋值首先需要赋值给 threadPoolId
                if (null == threadPoolId) {
                    threadPoolId = sb.toString();
                    sb.setLength(0);
                    // 如果 projectId 还没被赋值需要赋值给 projectId
                } else if (null == projectId) {
                    projectId = sb.toString();
                    sb.setLength(0);
                } else {
                    // 只可能出现两次 + ，如果出现第三次说明 groupKey 格式错误
                    throw new IllegalArgumentException("invalid groupkey:" + groupKey);
                }
                // 如果 groupKey 中出现了 %，需要判断是是否是转码的字符 + 或者 %
            } else if ('%' == c) {
                char next = groupKey.charAt(++i);
                char nextnext = groupKey.charAt(++i);
                // 如果是转码的字符 %2B，拼接 +
                if ('2' == next && 'B' == nextnext) {
                    sb.append('+');
                    // 如果是转码的字符 %25，拼接 %
                } else if ('2' == next && '5' == nextnext) {
                    sb.append('%');
                } else {
                    // 如果%号后面不是2B或者25，说明格式出现错误，因为在生成 groupKey 的时候已经将所有的 % 转码成为 %25
                    throw new IllegalArgumentException("invalid groupkey:" + groupKey);
                }
            } else {
                // 如果是普通字符，直接进行拼接
                sb.append(c);
            }
        }

        namespace = sb.toString();
        if (projectId.length() == 0) {
            throw new IllegalArgumentException("invalid groupkey:" + groupKey);
        }
        return new String[]{threadPoolId, projectId, namespace};
    }

    /**
     * 这里主要是将加号进行编码处理，防止根据 + 进行切分的时候因为数据中本来就带有加号
     *
     * @param str 需要编码的字符串
     * @param sb  编码处理后的结果
     */
    public static void urlEncode(String str, StringBuilder sb) {
        for (int idx = 0; idx < str.length(); ++idx) {
            char c = str.charAt(idx);
            if ('+' == c) {
                sb.append("%2B");
            } else if ('%' == c) {
                sb.append("%25");
            } else {
                sb.append(c);
            }
        }
    }

    public static String defaultThreadPoolId() {
        return "threadpool-" + UUID.randomUUID().toString().replace("-", "");
    }

}
